#include "Graph_Level.h"



Graph_Level::Graph_Level()
{
    ofstream monFlux("graph.xml");
}
Graph_Level::Graph_Level(Joueur* j,TextManager* t):j_(j),t_(t)
{
    //ctor
}



void Graph_Level::add_vertex(vertex v)
{
    Level* l=new Level(j_,t_);
    map<Type_Edge,vertex> t;
    t[ESC_DES]=vertex();
    t[ESC_MON]=vertex();
    t[PORTE1]=vertex();
    t[PORTE2]=vertex();
    graph_[v]=t;
    graph_lvl_[v]=l;

}
void Graph_Level::add_edge(vertex a, vertex b,Type_Edge id)
{
    graph_[a][id]=b;

    if(id==ESC_DES)
        id=ESC_MON;
    else if (id==ESC_MON)
        id=ESC_DES;

    graph_[b][id]=a;
}
vertex Graph_Level::getVertex(vertex a,Type_Edge b)
{
    return graph_[a][b];

}
void Graph_Level::creerVertex(vertex a,Type_Edge b)
{
    vertex nv;
    switch(b)
    {
        case ESC_DES:
            nv.niveau_=a.niveau_-1;     //On créer un level à l'étage d'en dessous
            nv.id_=graph_.size();
            add_vertex(nv);    //On associe le level au point sur le graph
            graph_[nv][ESC_MON]=a;          //On associe l'escalier montant du nvx point a l'origine
            graph_[a][b]=nv;                // Et l'escalier descendant de l'origine au nouveaux
        break;
        case ESC_MON:
            nv.niveau_=a.niveau_+1;
            nv.id_=graph_.size();
            add_vertex(nv);
            graph_[nv][ESC_DES]=a;
            graph_[a][b]=nv;
        break;
        default:
            nv.niveau_=a.niveau_;           //On reste sur le même etage
            nv.id_=graph_.size();
            add_vertex(nv);
            graph_[nv][b]=a;
            graph_[a][b]=nv;
        break;

    }

}
Level* Graph_Level::getLevel(vertex v)
{
    return graph_lvl_[v];
}
void Graph_Level::exportGraphML()
{
    map< vertex,map<Type_Edge,vertex> >::iterator it;
    map<Type_Edge,vertex>::iterator i2;
    int c=0;
    ofstream f("graph.graphml");
    f<<"<?xml version=\"1.0\" encoding=\"UTF-8\"?>"<<endl;
    f<<"<graph id=\"G\" edgedefault=\"undirected\">"<<endl;
    f<<"<key id=\"d0\" for=\"node\" attr.name=\"niveau\" attr.type=\"int\"> </key>";
    for(it=graph_.begin();it!=graph_.end();++it){
        f<<"<node id=\"n"+TextManager::to_string(it->first.id_)+"\" >"<<endl;
        f<< "<data key=\"d0\">"+TextManager::to_string(it->first.niveau_)+"</data>"<<endl;
        f<<"</node>"<<endl;

        }
    for(it=graph_.begin();it!=graph_.end();++it){
        for(i2=it->second.begin();i2!=it->second.end();++i2){
                if(i2->second.id_!=-1){
                    f<<"<edge id=\"e"+TextManager::to_string(c)+"\" source=\"n"+TextManager::to_string(it->first.id_)+"\" target=\"n"+TextManager::to_string(i2->second.id_)+"\"  />"<<endl;
                    c++;
                }
            }
        }
    f<<"</graph>";
    f.close();


}
int Graph_Level::getNiveau(vertex a,Type_Edge b)
{
        switch(b)
    {
        case ESC_DES:
            return a.niveau_-1;

        break;
        case ESC_MON:
            return a.niveau_+1;

        break;
        default:
            return a.niveau_;

        break;

    }

}
int Graph_Level::getNbrNiveau(int niv)
{
    map< vertex,map<Type_Edge,vertex> >::iterator it;
    int compteur=0;
    for(it=graph_.begin();it!=graph_.end();++it){
        if(it->first.niveau_ == niv)
            compteur++;

    }
    return compteur;
}
vertex Graph_Level::searchPossibleVertex(vertex v,Type_Edge t)
{
    map< vertex,map<Type_Edge,vertex> >::iterator it;
    vector<vertex> a,b;
    vector<vertex>::iterator itr;
    vertex retour;
    int niv=getNiveau(v,t); //On veut chercher dans le niveau d'arriver
    if(t==ESC_DES)
        t=ESC_MON;
    else if (t==ESC_MON)
        t=ESC_DES;

    for(it=graph_.begin();it!=graph_.end();++it){
        if( it->first.niveau_ == niv && !(it->first==v) && !(it->second[t].existe()) )   //On cherche tout les noeux au niveau niv
            a.push_back(it->first);
    }
    if(t==PORTE1 || t==PORTE2){
        for(itr=a.begin();itr!=a.end();++itr){
            if(graph_[*itr][PORTE1]!=v && graph_[*itr][PORTE2]!=v)
                b.push_back(*itr);
        }
        a=b;
    }
    if(!(a.empty()))
        retour=a[0];
    return retour;

}
